package c16多线程;

public class sleep和wait {

	public static void main(String[] args) {
		new Thread(new Thread1()).start();
		new Thread(new Thread2()).start();
	}


	private static class Thread1 implements Runnable {

		@Override
		public void run() {
			//由于这里的Thread1和下面的Thread2内部run方法要用同一对象作为监视器，我们这里不能用this，
			//因为在Thread2里面的this和这个Thread1的this不是同一个对象。
			//我们用sleep和wait.class这个字节码对象，当前虚拟机里引用这个变量时，指向的都是同一个对象。
			synchronized (sleep和wait.class) {
				System.err.println("enter thread1.");
				System.err.println("thread1 is sleeping...");
				try {
					Thread.sleep(3000);
				} catch (Exception e) {
					//TODO: handle exception
				}
				System.err.println("thread1 is waiting...");
				try {
					//@@释放锁有两种方式，第一种方式是程序自然离开监视器的范围，
					//也就是离开了synchronized关键字管辖的代码范围，另一种方式就是在synchronized关键字
					//管辖的代码内部调用监视器对象的wait方法。这里，使用wait方法释放锁。
					//释放锁后，Thread2获取该锁，开始执行Thread2
					sleep和wait.class.wait();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				//程序成功执行完wait代码后进入等待状态，当重新获得锁后会继续执行这下面的代码而不是重新执行！
				System.err.println("thread1 is going on.");
				System.err.println("thread1 is being over!");
			}
		}

	}

	private static class Thread2 implements Runnable {

		@Override
		public void run() {
			synchronized (sleep和wait.class) {
				System.err.println("enter thread2.");
				System.err.println("thread2 notify other thread can release wait status..");

				//notify方法并不释放锁，所以下面sleep代码会紧接着被执行，
				//而sleep也不会释放锁，所以直到下面的代码*处执行完才会释放锁
				sleep和wait.class.notify();

				System.err.println("thread2 is sleeping...");
				try {
					Thread.sleep(3000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}

				System.err.println("thread2 is going on.");
				System.err.println("thread2 is being over!");//*
			}
		}
	}

}
